<!--
 * @description: 
 * @Author: FengKongLi
 * @Date: 2022-10-19 10:02:29
 * @LastEditors: FengKongLi
 * @LastEditTime: 2022-10-19 16:50:23
-->
<template>
  <div class="container">
    <secen-view @already="already" id="view3D"></secen-view>
    <div class="toolbar">
      <div class="clear" @click="resetLoadScene">重新加载场景</div>
      <div class="clear" @click="handlerOpenSkyline">打开天际线</div>
      <div class="clear" @click="Close">关闭天际线</div>
    </div>
  </div>
</template>

<script>
let view3D = null;
export default {
  name: "SkylineAnalysis",
  data() {
    return {
      skylineAnayStages: null,
      // silhouette的效果可以理解为物体轮廓、描边，相当于把物体的外轮廓线勾勒出来
      silhouette: null,
    };
  },

  methods: {
    already(viewer) {
      view3D = viewer;
      this.loadModel();
    },
    // 首先把模型加载到地图上
    loadModel() {
      let modelposition = Cesium.Cartesian3.fromDegrees(-74.0, 40.6, 0);
      // toRadians将度数转换为弧度。
      let heading = Cesium.Math.toRadians(0.0);
      let pitch = Cesium.Math.toRadians(0.0);
      let roll = Cesium.Math.toRadians(0.0);
      // HeadingPitchRoll 表示为航向、俯仰和滚动的旋转。航向是围绕负 z 轴的旋转。俯仰是围绕负 y 轴的旋转。滚动是围绕正 x 轴的旋转。
      let hpRoll = new Cesium.HeadingPitchRoll(heading, pitch, roll);
      let converter = Cesium.Transforms.eastNorthUpToFixedFrame;
      let modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
        modelposition,
        hpRoll,
        Cesium.Ellipsoid.WGS84,
        converter
      );
      let tsdyt_model = view3D.scene.primitives.add(
        new Cesium.Cesium3DTileset({
          url: "http://earthsdk.com/v/last/Apps/assets/dayanta/tileset.json",
        })
      );
      tsdyt_model.readyPromise.then(function (tsdyt_model) {
        //请求模型后执行
        tsdyt_model._root.transform = modelMatrix; //模型位置
      });
      view3D.zoomTo(tsdyt_model);
    },

    // * 进行天际线分析
    handlerOpenSkyline() {
      if (this.skylineAnayStages) {
        this.silhouette.enabled = true;
        return;
      }
      // postProcessStages后期处理效果应用到最终渲染。
      this.skylineAnayStages = view3D.scene.postProcessStages;
      // PostProcessStageLibrary包含用于创建公共后处理阶段的函数。
      // createEdgeDetectionStage创建检测边缘的后处理阶段。将颜色写入输出纹理，当它处于边缘时，alpha 设置为1.0。
      let edgeDetection =
        Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
      // Cesium.PostProcessStage在场景渲染的纹理或前一个后处理阶段的输出上运行后处理阶段。
      let postProccessStage = new Cesium.PostProcessStage({
        //此后处理阶段的唯一名称，供组合中其他阶段参考，如果未提供名称，将自动生成GUID
        // name:name,
        //unform着色器对象 textureScale
        fragmentShader:
          "uniform sampler2D colorTexture;" +
          "uniform sampler2D depthTexture;" +
          "varying vec2 v_textureCoordinates;" +
          "void main(void)" +
          "{" +
          "float depth = czm_readDepth(depthTexture, v_textureCoordinates);" +
          "vec4 color = texture2D(colorTexture, v_textureCoordinates);" +
          "if(depth<1.0 - 0.000001){" +
          "gl_FragColor = color;" +
          "}" +
          "else{" +
          "gl_FragColor = vec4(1.0,0.0,0.0,1.0);" +
          "}" +
          "}",
      });

      //PostProcessStage:要使用的片段着色器。默认sampler2D制服是colorTexture和depthTexture。
      let postProccesStage_1 = new Cesium.PostProcessStage({
        // name:obj.name+'_1',
        fragmentShader:
          "uniform sampler2D colorTexture;" +
          "uniform sampler2D redTexture;" +
          "uniform sampler2D silhouetteTexture;" +
          "varying vec2 v_textureCoordinates;" +
          "void main(void)" +
          "{" +
          "vec4 redcolor=texture2D(redTexture, v_textureCoordinates);" +
          "vec4 silhouetteColor = texture2D(silhouetteTexture, v_textureCoordinates);" +
          "vec4 color = texture2D(colorTexture, v_textureCoordinates);" +
          "if(redcolor.r == 1.0){" +
          "gl_FragColor = mix(color, vec4(5.0,0.0,0.0,1.0), silhouetteColor.a);" +
          "}" +
          "else{" +
          "gl_FragColor = color;" +
          "}" +
          "}",
        //uniform着色器对象
        uniforms: {
          redTexture: postProccessStage.name,
          silhouetteTexture: edgeDetection.name,
        },
      });

      //如果inputPreviousStageTexture 是 true，则每个阶段输入是场景渲染到的输出纹理或之前执行阶段的输出纹理
      //如果inputPreviousStageTexture是false，则合成中每个阶段的输入纹理都是相同的
      this.silhouette = new Cesium.PostProcessStageComposite({
        //PostProcessStage要按顺序执行 的 s 或组合的数组。
        stages: [edgeDetection, postProccessStage, postProccesStage_1],
        //是否执行每个后处理阶段，其中一个阶段的输入是前一个阶段的输出。否则每个包含阶段的输入是组合之前执行的阶段的输出
        inputPreviousStageTexture: false,
        //后处理阶段制服的别名
        uniforms: edgeDetection.uniforms,
      });
      this.skylineAnayStages.add(this.silhouette);
    },

    Close() {
      this.silhouette.enabled = false;
    },
    resetLoadScene() {
      this.loadModel();
    },
  },
};
</script>
<style lang="scss" scoped>
.container {
  position: relative;
  .toolbar {
    background: rgba($color: #000000, $alpha: 0.6);
    position: absolute;
    top: 1rem;
    color: white;
    padding: 1rem;
    .clear {
      border: white solid 1px;
      padding: 0.5rem 1rem;
    }
  }
}
</style>
